/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gblend.adjlistgraph;

import gblend.frequentindex.Vertex;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.HashSet;
import java.util.Vector;

/*
 * Copyright 2010, Center for Advanced Information Systems,Nanyang Technological University
 *
 * File name: ALGraph.java
 *
 * Abstract: The graph structure
 *
 * Current Version:      0.1
 * Auther:               Jin Changjiu
 * Modified Date:        Feb 28,2010
 *
 */
public class ALGraph {

    private Vertex[] vertexes = null;
    //  private HashMap<Integer, Link> adjTab = null;
    private Link[] adjTab = null;
    private int pos = -1;
    private int edgeNum = 0;
    private int nodeNum = 0;
    private HashSet<Integer> graphid = new HashSet<Integer>();
    private String cam = null;
    //FOR WHAT? The ID List of Graph that contain this graph?
    private HashSet<FsgIdEntry> idlist = new HashSet<FsgIdEntry>();
    private boolean isVisited;
    private ArrayList<Integer> Succ = new ArrayList<Integer>();
    private Vector<Integer> children = new Vector<Integer>();
    private Vector<Integer> clusterlist = new Vector<Integer>();
    //FOR LARGE GRAPH
    private HashMap<Integer, Vector<Integer>> graphnodelist = new HashMap<Integer, Vector<Integer>>();
      private HashSet<Integer> boundary = new HashSet<Integer>();
    //An on-hold id list, to be used when extra mining frequent fragments with graph
    //combining
    //   private HashSet<FsgIdEntry> holdidlist = new HashSet<FsgIdEntry>();

    public ALGraph(int size) {
        vertexes = new Vertex[size];
        //   adjTab = new HashMap<Integer, Link>();
        adjTab = new Link[size];
        for (int i = 0; i < size; i++) {
            adjTab[i] = new Link();
        }
    }

    public void addnode(Vertex node) {
        assert pos < vertexes.length;
        vertexes[++pos] = node;
        //  adjTab.put(node.getId(), new Link());
    }

    public void addEdge(int from, int to) {
        /*adjTab.get(from).add(to);
        adjTab.get(to).add(from);*/
        adjTab[from].add(to);
        adjTab[to].add(from);
    }

    public void delEdge(int from, int to) {
        /*adjTab.get(from).remove(to);
        adjTab.get(to).remove(from);*/
        adjTab[from].remove(to);
        adjTab[to].remove(from);
    }

    public int getEdge(int from, int to) {
        // Node p = adjTab.get(from).first();
        Node p = adjTab[from].first();
        while (p != null) {
            if (p.index() == to) {
                return 1;
            }
            p = p.next();
        }

        return 0;
    }

    public int getNnum() {
        return nodeNum;
    }

    public void setNnum(int num) {
        nodeNum = num;
    }

    public void setEnum(int num) {
        edgeNum = num;
    }

    public int getEnum() {
        return edgeNum;
    }

    public Vertex getNode(int index) {
        return vertexes[index];
    }

    /**
     * SEEMS LIKE THIS 1 IS NOT IN USE 8-}
     * @param nodeId
     * @return
     */
    public Link getLink(int nodeId) {
      //  return adjTab.get(nodeId);
        return adjTab[nodeId];
    }

    public void setGraphid(int gid) {
        graphid.add(gid);
    }

    public void setAllGraphid(HashSet<Integer> gidset) {
        graphid = new HashSet<Integer>(gidset);
    }

    public Integer[] getGraphid() {
        Vector<Integer> gid = new Vector<Integer>(graphid);
        Collections.sort(gid);
        return gid.toArray(new Integer[0]);
    }

    public HashSet<Integer> getGraphidAsSet() {
        return graphid;
    }

    public FsgIdEntry getGraphidAsEntry() {
        return new FsgIdEntry(graphid);
    }
//SEEMS LIKE THIS 1 NOT IN USE 8-}
    /*
    //display the Adjlist
    public void dispAdjList() {
    Node p = null;
    for (int i = 0; i < nodeNum; i++) {
    System.out.println(i + ":");
    p = adjTab[i].first();
    while (p != null) {
    System.out.print("[" + i + "," + p.index() + "]" + " -> ");
    p = p.next();
    }
    System.out.println();
    }
    }*/

    public void setCam(String line) {
        cam = line;
    }

    public String getCam() {
        return cam;
    }

    public void setidlist(FsgIdEntry gid) {
        if (idlist.add(gid)) {
            //   System.out.println("Really add to id list");
        }
    }

    public HashSet<FsgIdEntry> getidlist() {
        return idlist;
    }

    public boolean isVisited() {
        return isVisited;
    }

    public void clean() {
        isVisited = false;
    }

    public void visit() {
        isVisited = true;
    }

    public void setSucc(int node) {
        Succ.add(node);
    }

    public ArrayList<Integer> getSucc() {
        return Succ;
    }

    public void setChildren(int nodeid) {
        children.addElement(nodeid);
    }

    public Vector<Integer> getChildren() {
        return children;
    }

    public void setClusters(int cid) {
        clusterlist.addElement(cid);
    }

    public Vector<Integer> getClusters() {
        return clusterlist;
    }

    //FOR LARGE GRAPH
    public HashSet<Integer> getBoundaryVertices() {
    return boundary;
    }

    public void addBoundaryVertex(int id) {
    boundary.add(id);
    }
    public Vertex[] getVertices() {
        return vertexes;
    }

    public Link getAdjLink(int from) {
        return adjTab[from];
    }

    /**
     * This is for LARGE graph algo
     * @param elementAt
     * @param child
     * @return
     
    public static int[][] candidateRemovedEdges(ALGraph parent, ALGraph child) {
        Vector<Integer> result = new Vector<Integer>();
        int vl = child.edgeNum + 1;
        System.out.println("vl=" + vl);
        Vector[] sizenparent = new Vector[vl], sizenchild = new Vector[vl];
        for (int i = 0; i < vl; i++) {
            sizenparent[i] = new Vector<Integer>();
            sizenchild[i] = new Vector<Integer>();
        }

        for (int i = 0; i < parent.nodeNum; i++) {
            sizenparent[parent.vertexes[i].getDegree()].add(parent.vertexes[i].getId());
            sizenchild[child.vertexes[i].getDegree()].add(child.vertexes[i].getId());
        }
        // sizenchild[child.vertexes[vl].getDegree()].add(child.vertexes[vl].getId());
        int lostdegree = 0, j = 0;
        int[] whatdegree = new int[2];
        whatdegree[0] = whatdegree[1] = 0;
        for (int i = 1; (lostdegree < 2) && (i < vl); i++) {
            int change = sizenchild[i].size() - sizenparent[i].size();
            if (change > 0) {

                lostdegree += change;
                whatdegree[j] = i;
                j++;
                //s   System.out.println("lostdegree="+lostdegree+",change="+change+",i="+i+",j="+j);
            }
        }

        if (whatdegree[1] == 0) {
            Iterator<Integer> temp = sizenchild[whatdegree[0]].iterator();
            while (temp.hasNext()) {
                int nodeid = temp.next();
                Node p = child.adjTab[nodeid].first();
                while (p != null) {
                    int pid = p.index();
                    if ((pid > nodeid) && (sizenchild[whatdegree[0]].contains(pid))) {
                        result.add(nodeid);
                        result.add(pid);
                    }
                    p = p.next();
                }
            }
        } else {
            Iterator<Integer> temp = sizenchild[whatdegree[0]].iterator();
            while (temp.hasNext()) {
                int nodeid = temp.next();
                Node p = child.adjTab[nodeid].first();
                while (p != null) {
                    int pid = p.index();
                    if ((pid > nodeid) && (sizenchild[whatdegree[1]].contains(pid))) {
                        result.add(nodeid);
                        result.add(pid);
                    }
                    p = p.next();
                }
            }
        }
        int[][] resa = new int[result.size() / 2][2];
        Iterator<Integer> restoresa = result.iterator();
        int i = 0;
        while (restoresa.hasNext()) {
            resa[i][0] = restoresa.next();
            resa[i][1] = restoresa.next();
            i++;
        }
        return resa;
    }*/

    /**
     * nodeid is local, node1 should has label smaller than that of node 2
     * @param graphId
     * @param nodeid1
     * @param nodeid2
     */
    public void addExtendIdList(int gid, int nodeid1, int nodeid2) {
        Vector<Integer> ls = graphnodelist.get(gid);
        if (ls == null) {
            ls = new Vector<Integer>();
            ls.add(nodeid1);
            ls.add(nodeid2);
            graphnodelist.put(gid, ls);
        } else {
            ls.add(nodeid1);
            ls.add(nodeid2);
        }
    }

    public HashMap<Integer, Vector<Integer>> getExtendIdList() {
        return graphnodelist;
    }

    public void setAllidlist(HashSet<FsgIdEntry> idlist) {
       this.idlist=idlist;
    }
    /*public void addHoldIdList(FsgIdEntry nId){
    holdidlist.add(nId);
    }

    public HashSet<FsgIdEntry> getOnHoldList(){
    return holdidlist;
    }

    public void combineHoldIdList(){
    idlist.addAll(holdidlist);
    holdidlist.clear();
    }*/
}
